using System;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;

namespace MesProjectWinform.Helper
{
    /// <summary>
    /// 密码加密和解密帮助类
    /// </summary>
    public static class PasswordHelper
    {
        #region MD5加密（不可逆）

        /// <summary>
        /// MD5加密（不可逆）
        /// </summary>
        /// <param name="input">需要加密的字符串</param>
        /// <returns>MD5加密后的字符串</returns>
        public static string GetMD5(this string input)
        {
            if (string.IsNullOrEmpty(input))
            {
                return string.Empty;
            }

            using (MD5 md5 = MD5.Create())
            {
                byte[] inputBytes = Encoding.UTF8.GetBytes(input);
                byte[] hashBytes = md5.ComputeHash(inputBytes);

                // 将字节数组转换成十六进制字符串
                StringBuilder sb = new StringBuilder();
                for (int i = 0; i < hashBytes.Length; i++)
                {
                    sb.Append(hashBytes[i].ToString("x2"));
                }
                return sb.ToString();
            }
        }

        /// <summary>
        /// MD5加密（不可逆）- 16位
        /// </summary>
        /// <param name="input">需要加密的字符串</param>
        /// <returns>16位MD5加密后的字符串</returns>
        public static string GetMD5_16(this string input)
        {
            return GetMD5(input).Substring(8, 16);
        }

        #endregion

        #region SHA256加密（不可逆，比MD5更安全）

        /// <summary>
        /// SHA256加密（不可逆）
        /// </summary>
        /// <param name="input">需要加密的字符串</param>
        /// <returns>SHA256加密后的字符串</returns>
        public static string GetSHA256(this string input)
        {
            if (string.IsNullOrEmpty(input))
            {
                return string.Empty;
            }

            using (SHA256 sha256 = SHA256.Create())
            {
                byte[] inputBytes = Encoding.UTF8.GetBytes(input);
                byte[] hashBytes = sha256.ComputeHash(inputBytes);

                // 将字节数组转换成十六进制字符串
                StringBuilder sb = new StringBuilder();
                for (int i = 0; i < hashBytes.Length; i++)
                {
                    sb.Append(hashBytes[i].ToString("x2"));
                }
                return sb.ToString();
            }
        }

        #endregion

        #region AES加密和解密（可逆）

        /// <summary>
        /// AES加密密钥（32位）
        /// </summary>
        private static readonly string AesKey = "MesProjectWinform_Security_Key_32";

        /// <summary>
        /// AES加密向量（16位）
        /// </summary>
        private static readonly string AesIV = "MesProject_IV_16";

        /// <summary>
        /// AES加密（可逆）
        /// </summary>
        /// <param name="input">需要加密的字符串</param>
        /// <param name="key">密钥（可选，默认使用内置密钥）</param>
        /// <param name="iv">向量（可选，默认使用内置向量）</param>
        /// <returns>加密后的Base64字符串</returns>
        public static string AesEncrypt(this string input, string key = null, string iv = null)
        {
            if (string.IsNullOrEmpty(input))
            {
                return string.Empty;
            }

            byte[] keyBytes = Encoding.UTF8.GetBytes((key ?? AesKey).PadRight(32).Substring(0, 32));
            byte[] ivBytes = Encoding.UTF8.GetBytes((iv ?? AesIV).PadRight(16).Substring(0, 16));
            byte[] inputBytes = Encoding.UTF8.GetBytes(input);

            using (Aes aes = Aes.Create())
            {
                aes.Key = keyBytes;
                aes.IV = ivBytes;
                aes.Mode = CipherMode.CBC;
                aes.Padding = PaddingMode.PKCS7;

                using (MemoryStream memoryStream = new MemoryStream())
                {
                    using (CryptoStream cryptoStream = new CryptoStream(memoryStream, aes.CreateEncryptor(), CryptoStreamMode.Write))
                    {
                        cryptoStream.Write(inputBytes, 0, inputBytes.Length);
                        cryptoStream.FlushFinalBlock();
                    }

                    return Convert.ToBase64String(memoryStream.ToArray());
                }
            }
        }

        /// <summary>
        /// AES解密
        /// </summary>
        /// <param name="encryptedText">加密后的Base64字符串</param>
        /// <param name="key">密钥（可选，默认使用内置密钥）</param>
        /// <param name="iv">向量（可选，默认使用内置向量）</param>
        /// <returns>解密后的字符串</returns>
        public static string AesDecrypt(this string encryptedText, string key = null, string iv = null)
        {
            if (string.IsNullOrEmpty(encryptedText))
            {
                return string.Empty;
            }

            try
            {
                byte[] keyBytes = Encoding.UTF8.GetBytes((key ?? AesKey).PadRight(32).Substring(0, 32));
                byte[] ivBytes = Encoding.UTF8.GetBytes((iv ?? AesIV).PadRight(16).Substring(0, 16));
                byte[] encryptedBytes = Convert.FromBase64String(encryptedText);

                using (Aes aes = Aes.Create())
                {
                    aes.Key = keyBytes;
                    aes.IV = ivBytes;
                    aes.Mode = CipherMode.CBC;
                    aes.Padding = PaddingMode.PKCS7;

                    using (MemoryStream memoryStream = new MemoryStream())
                    {
                        using (CryptoStream cryptoStream = new CryptoStream(memoryStream, aes.CreateDecryptor(), CryptoStreamMode.Write))
                        {
                            cryptoStream.Write(encryptedBytes, 0, encryptedBytes.Length);
                            cryptoStream.FlushFinalBlock();
                        }

                        return Encoding.UTF8.GetString(memoryStream.ToArray());
                    }
                }
            }
            catch (Exception ex)
            {
                // 解密失败，返回空字符串
                return string.Empty;
            }
        }

        #endregion

        #region DES加密和解密（可逆）

        /// <summary>
        /// DES加密密钥（8位）
        /// </summary>
        private static readonly string DesKey = "MesKey_8";

        /// <summary>
        /// DES加密向量（8位）
        /// </summary>
        private static readonly string DesIV = "MesIV_8_";

        /// <summary>
        /// DES加密（可逆）
        /// </summary>
        /// <param name="input">需要加密的字符串</param>
        /// <param name="key">密钥（可选，默认使用内置密钥）</param>
        /// <param name="iv">向量（可选，默认使用内置向量）</param>
        /// <returns>加密后的Base64字符串</returns>
        public static string DesEncrypt(this string input, string key = null, string iv = null)
        {
            if (string.IsNullOrEmpty(input))
            {
                return string.Empty;
            }

            byte[] keyBytes = Encoding.UTF8.GetBytes((key ?? DesKey).PadRight(8).Substring(0, 8));
            byte[] ivBytes = Encoding.UTF8.GetBytes((iv ?? DesIV).PadRight(8).Substring(0, 8));
            byte[] inputBytes = Encoding.UTF8.GetBytes(input);

            using (DES des = DES.Create())
            {
                des.Key = keyBytes;
                des.IV = ivBytes;
                des.Mode = CipherMode.CBC;
                des.Padding = PaddingMode.PKCS7;

                using (MemoryStream memoryStream = new MemoryStream())
                {
                    using (CryptoStream cryptoStream = new CryptoStream(memoryStream, des.CreateEncryptor(), CryptoStreamMode.Write))
                    {
                        cryptoStream.Write(inputBytes, 0, inputBytes.Length);
                        cryptoStream.FlushFinalBlock();
                    }

                    return Convert.ToBase64String(memoryStream.ToArray());
                }
            }
        }

        /// <summary>
        /// DES解密
        /// </summary>
        /// <param name="encryptedText">加密后的Base64字符串</param>
        /// <param name="key">密钥（可选，默认使用内置密钥）</param>
        /// <param name="iv">向量（可选，默认使用内置向量）</param>
        /// <returns>解密后的字符串</returns>
        public static string DesDecrypt(this string encryptedText, string key = null, string iv = null)
        {
            if (string.IsNullOrEmpty(encryptedText))
            {
                return string.Empty;
            }

            try
            {
                byte[] keyBytes = Encoding.UTF8.GetBytes((key ?? DesKey).PadRight(8).Substring(0, 8));
                byte[] ivBytes = Encoding.UTF8.GetBytes((iv ?? DesIV).PadRight(8).Substring(0, 8));
                byte[] encryptedBytes = Convert.FromBase64String(encryptedText);

                using (DES des = DES.Create())
                {
                    des.Key = keyBytes;
                    des.IV = ivBytes;
                    des.Mode = CipherMode.CBC;
                    des.Padding = PaddingMode.PKCS7;

                    using (MemoryStream memoryStream = new MemoryStream())
                    {
                        using (CryptoStream cryptoStream = new CryptoStream(memoryStream, des.CreateDecryptor(), CryptoStreamMode.Write))
                        {
                            cryptoStream.Write(encryptedBytes, 0, encryptedBytes.Length);
                            cryptoStream.FlushFinalBlock();
                        }

                        return Encoding.UTF8.GetString(memoryStream.ToArray());
                    }
                }
            }
            catch (Exception ex)
            {
                // 解密失败，返回空字符串
                return string.Empty;
            }
        }

        #endregion

        #region 密码哈希（安全存储密码）

        /// <summary>
        /// 创建安全的密码哈希（使用PBKDF2算法，包含盐值）
        /// </summary>
        /// <param name="password">原始密码</param>
        /// <returns>哈希后的密码（格式：盐值:哈希值）</returns>
        public static string CreatePasswordHash(this string password)
        {
            if (string.IsNullOrEmpty(password))
            {
                return string.Empty;
            }

            // 创建随机盐值
            byte[] salt = new byte[16];
            using (var rng = RandomNumberGenerator.Create())
            {
                rng.GetBytes(salt);
            }

            // 使用PBKDF2算法创建哈希
            byte[] hash = GetPbkdf2Hash(password, salt, 10000, 32);

            // 将盐值和哈希组合起来（盐值:哈希值）
            return Convert.ToBase64String(salt) + ":" + Convert.ToBase64String(hash);
        }

        /// <summary>
        /// 验证密码是否匹配哈希
        /// </summary>
        /// <param name="password">输入的密码</param>
        /// <param name="hashedPassword">存储的哈希密码（格式：盐值:哈希值）</param>
        /// <returns>密码是否匹配</returns>
        public static bool VerifyPasswordHash(this string password, string hashedPassword)
        {
            if (string.IsNullOrEmpty(password) || string.IsNullOrEmpty(hashedPassword))
            {
                return false;
            }

            // 分离盐值和哈希值
            string[] parts = hashedPassword.Split(':');
            if (parts.Length != 2)
            {
                return false;
            }

            try
            {
                byte[] salt = Convert.FromBase64String(parts[0]);
                byte[] hash = Convert.FromBase64String(parts[1]);

                // 使用相同的参数和盐值计算哈希
                byte[] newHash = GetPbkdf2Hash(password, salt, 10000, hash.Length);

                // 比较哈希
                return hash.SequenceEqual(newHash);
            }
            catch
            {
                return false;
            }
        }

        private static byte[] GetPbkdf2Hash(string password, byte[] salt, int iterations, int outputBytes)
        {
            using (var pbkdf2 = new Rfc2898DeriveBytes(password, salt, iterations))
            {
                return pbkdf2.GetBytes(outputBytes);
            }
        }

        #endregion
    }
} 